package com.hdd.biz.finance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hdd.biz.account.entity.Account;
import com.hdd.biz.account.service.AccountBillService;
import com.hdd.biz.account.service.AccountService;
import com.hdd.biz.finance.dto.WithdrawCreateRequest;
import com.hdd.biz.finance.dto.WithdrawListRequest;
import com.hdd.biz.finance.dto.WithdrawRecordRequest;
import com.hdd.biz.finance.dto.WithdrawVerifyRequest;
import com.hdd.biz.finance.entity.Withdraw;
import com.hdd.biz.finance.mapper.WithdrawMapper;
import com.hdd.biz.finance.service.WithdrawService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hdd.biz.member.entity.Member;
import com.hdd.biz.member.service.MemberService;
import com.hdd.dto.SuperResponse;
import com.hdd.utils.IdUtils;
import com.hdd.utils.alipay.AliPayUtils;
import com.hdd.utils.wx.WxMiniProgramUtil;
import com.hdd.utils.wx.pay.PayUtil;
import com.hdd.utils.wx.pay.WeiXinPayEntity;
import com.hdd.utils.wx.pay.WeixinPay;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 提现表 服务实现类
 * </p>
 *
 * @author fang
 * @since 2021-02-23
 */
@Service
@Slf4j
public class WithdrawServiceImpl extends ServiceImpl<WithdrawMapper, Withdraw> implements WithdrawService {

    @Autowired
    private WxMiniProgramUtil wxMiniProgramUtil;
    @Autowired
    private AccountService accountService;
    @Autowired
    private AccountBillService billService;
    @Autowired
    private MemberService memberService;
    @Value("${wx.p12}")
    private String wxP12;
    @Override
    public SuperResponse withdrawList(WithdrawListRequest request) {
        SuperResponse response = new SuperResponse();
        QueryWrapper<Withdraw> wrapper = new QueryWrapper();
        Page<Withdraw> pages = new Page<>(request.getPageNo(),request.getPageSize());
        if(!StringUtils.isEmpty(request.getStatus())){
            wrapper.like("status",request.getStatus());
        }
        wrapper.orderByDesc("create_time");
        IPage<Withdraw> mapIPage = baseMapper.selectPage(pages, wrapper);
        List<Withdraw> list = mapIPage.getRecords();
        response.setItems(list);
        response.setTotals(mapIPage.getTotal());
        return response;
    }


    @Override
    public SuperResponse verifyWithdraw(WithdrawVerifyRequest request) {
        SuperResponse response = new SuperResponse();

        Withdraw withdraw = findWithdrawById(request.getId());

        if(withdraw==null){
            response.setCode(-1000);
            response.setMessage("提现记录不存在");
            return response;
        }

        if(!"F".equals(withdraw.getStatus())){
            response.setCode(-1000);
            response.setMessage("请勿重复审核");
            return response;
        }

        if(withdraw==null){
            response.setCode(-1000);
            response.setMessage("提现失败");
            return response;
        }
        Account account = accountService.findAccount(withdraw.getUserId());
        if(account==null){
            response.setCode(-1000);
            response.setMessage("账户不存在");
            return response;
        }

        if(account.getFrozen().compareTo(withdraw.getAmount())==-1){
            response.setCode(-1000);
            response.setMessage("账户异常");
            return response;
        }

        //开始支付宝提现
        SuperResponse aliRes = AliPayUtils.alipay2User(withdraw.getOrderNo(),withdraw.getAmount().toString(),withdraw.getAccount(),withdraw.getRealName());
        if(aliRes.getCode()==200){
            //设置钱
            accountService.reduceFrozen(account.getId(),withdraw.getAmount());
            withdraw.setStatus("T");
            withdraw.setRemarks("转账成功");
            baseMapper.updateById(withdraw);
            wxMiniProgramUtil.sendWithdrawalMessage(withdraw.getUserId(),withdraw.getRealName(),"已提现到你指定账户，敬请查收哦。",withdraw.getAmount().doubleValue(),"提现成功");
        }else{
            //回滚钱
            accountService.reduceFrozen(account.getId(),withdraw.getAmount());
            accountService.increBlance(account.getId(),withdraw.getAmount());
            billService.addBill(account.getId(),withdraw.getAmount(),"I","提现退回","0",withdraw.getAmount().toString(),"0",1);
            withdraw.setStatus("R");
            withdraw.setRemarks(aliRes.getMessage());
            baseMapper.updateById(withdraw);
            wxMiniProgramUtil.sendWithdrawalMessage(withdraw.getUserId(),withdraw.getRealName(),"提现账户信息错误，请修改后再提现哦。",withdraw.getAmount().doubleValue(),"提现失败");
        }

        return response;
    }


    @Override
    public SuperResponse weiXinVerify(WithdrawVerifyRequest request) {
        SuperResponse response = new SuperResponse();

        Withdraw withdraw = findWithdrawById(request.getId());

        if(withdraw==null){
            response.setCode(-1000);
            response.setMessage("提现记录不存在");
            return response;
        }

        if(!"F".equals(withdraw.getStatus())){
            response.setCode(-1000);
            response.setMessage("请勿重复审核");
            return response;
        }

        if(withdraw==null){
            response.setCode(-1000);
            response.setMessage("提现失败");
            return response;
        }
        Account account = accountService.findAccount(withdraw.getUserId());
        if(account==null){
            response.setCode(-1000);
            response.setMessage("账户不存在");
            return response;
        }

        if(account.getFrozen().compareTo(withdraw.getAmount())==-1){
            response.setCode(-1000);
            response.setMessage("账户异常");
            return response;
        }

        Member member = memberService.findMemberByUid(account.getUserId());
        //开始支付宝提现

        try {
            WeiXinPayEntity weiXinPayEntity =  pay(withdraw.getOrderNo(),member.getXcxOpenid(),withdraw.getRealName(),withdraw.getAmount().doubleValue(),"提现","127.0.0.1");
            if("SUCC".equals(weiXinPayEntity.getCode())){
                //设置钱
                accountService.reduceFrozen(account.getId(),withdraw.getAmount());
                withdraw.setStatus("T");
                withdraw.setRemarks("转账成功");
                baseMapper.updateById(withdraw);
                wxMiniProgramUtil.sendWithdrawalMessage(withdraw.getUserId(),withdraw.getRealName(),"提现已处理，敬请查收哦。",withdraw.getAmount().doubleValue(),"提现成功");
            }else{
                //回滚钱
                accountService.reduceFrozen(account.getId(),withdraw.getAmount());
                accountService.increBlance(account.getId(),withdraw.getAmount());
                billService.addBill(account.getId(),withdraw.getAmount(),"I","提现退回","0",withdraw.getAmount().toString(),"0",1);
                withdraw.setStatus("R");
                withdraw.setRemarks(weiXinPayEntity.getCode());
                baseMapper.updateById(withdraw);
                wxMiniProgramUtil.sendWithdrawalMessage(withdraw.getUserId(),withdraw.getRealName(),weiXinPayEntity.getCode(),withdraw.getAmount().doubleValue(),"提现失败");
                response.setCode(-1000);
                return response;
            }

        }catch (Exception e){
            e.printStackTrace();
        }
        return response;
    }


    public WeiXinPayEntity pay(String orderNo,String  weixinOpenId,String realname,Double payAmount, String desc, String ip) throws Exception{
        File pkcFile = ResourceUtils.getFile(wxP12);
        Object result[] = WeixinPay.payToUser(pkcFile, orderNo, weixinOpenId, realname, payAmount, desc, ip);
        String resXml = (String) result[1];
        boolean postError = (Boolean) result[0];
        WeiXinPayEntity weiXinPayEntity = new WeiXinPayEntity();
        weiXinPayEntity.setCode("ERROR");
        if (!postError) {
            Map<String, String> map = new HashMap<String, String>();
            try {
                map = PayUtil.parseXMLToMap(resXml);
            } catch (Exception e) {
                e.printStackTrace();
            }
            String returnCode = map.get("return_code");
            if (returnCode.equalsIgnoreCase("FAIL")) {
                //支付失败
                weiXinPayEntity.setCode(map.get("return_msg")+":"+map.get("err_code_des"));
                return weiXinPayEntity;
            } else if (returnCode.equalsIgnoreCase("SUCCESS")) {
                if (map.get("err_code") != null) {
                    //支付失败
                    weiXinPayEntity.setCode(map.get("return_msg")+":"+map.get("err_code_des"));
                    return weiXinPayEntity;
                } else if (map.get("result_code").equalsIgnoreCase(
                        "SUCCESS")) {
                    //支付成功  paymentNo：微信付款单号  payment_time：付款成功时间
                    String paymentNo = map.get("payment_no");
                    String paymentTradeNo = map.get("partner_trade_no");
                    String payment_time = map.get("payment_time");
                    try {
                        weiXinPayEntity.setOrderNo(paymentTradeNo);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    weiXinPayEntity.setCode("SUCC");
                    return weiXinPayEntity;
                }
            }
        }

        weiXinPayEntity.setCode("ERROR");
        return weiXinPayEntity;
    }

    @Override
    public SuperResponse createWithdraw(WithdrawCreateRequest request) {
        return null;
    }

    @Override
    public SuperResponse withdrawRecord(WithdrawRecordRequest request) {
        return null;
    }

    @Override
    public boolean insertWithdraw(String userId, BigDecimal amount, String platform, String account, String real_name) {
        Withdraw withdraw = new Withdraw();
        withdraw.setOrderNo(IdUtils.getNum14());
        withdraw.setUserId(userId);
        withdraw.setAmount(amount);
        withdraw.setPlatform(platform);
        withdraw.setAccount(account);
        withdraw.setStatus("F");
        withdraw.setRealName(real_name);
        return baseMapper.insert(withdraw)>0?true:false;
    }


    @Override
    public int insertWithdraws(String userId, BigDecimal amount, String platform, String account, String real_name) {
        Withdraw withdraw = new Withdraw();
        withdraw.setOrderNo(IdUtils.getNum14());
        withdraw.setUserId(userId);
        withdraw.setAmount(amount);
        withdraw.setPlatform(platform);
        withdraw.setAccount(account);
        withdraw.setStatus("F");
        withdraw.setRealName(real_name);
        baseMapper.insert(withdraw);
        return withdraw.getId();
    }

    @Override
    public Withdraw findWithdrawById(Integer id) {
        return baseMapper.selectById(id);
    }


    @Override
    public Double todayWithdraw() {

        return baseMapper.todayWithdraw();
    }

    @Override
    public Double totalWithdraw() {
        return baseMapper.totalWithdraw();
    }

    @Override
    public Double yesterdayWithdraw() {
        return baseMapper.yesterdayWithdraw();
    }

    @Override
    public Double weekWithdraw() {
        return baseMapper.weekWithdraw();
    }

    @Override
    public Double monthWithdraw() {
        return baseMapper.monthWithdraw();
    }
}
